package com.generic.action;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.struts2.convention.annotation.Action;
import org.apache.struts2.convention.annotation.InterceptorRef;
import org.apache.struts2.convention.annotation.Result;
import org.apache.struts2.interceptor.validation.SkipValidation;

import com.generic.dao.impl.MemberDao;
import com.generic.ds.HibernateSession;
import com.generic.module.impl.Member;
import com.generic.util.Constant;
import com.generic.util.Encoder;
import com.generic.util.MailService;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.validator.annotations.EmailValidator;
import com.opensymphony.xwork2.validator.annotations.FieldExpressionValidator;
import com.opensymphony.xwork2.validator.annotations.RequiredStringValidator;
import com.opensymphony.xwork2.validator.annotations.StringLengthFieldValidator;

@InterceptorRef("jsonValidationWorkflowStack")
public class SignUp extends ActionSupport {

	private static final long serialVersionUID = 4822689189743604387L;
	private String email = null;
	private String password = null;
	private String firstName = null;
	private String lastName = null;
	private String gender = null;
	private List<Integer> years;
	private Integer year;
	private Map<Integer,String> months;
	private Integer month;
	private List<Integer> days;
	private Integer day;
	
	public SignUp() {
		years = new ArrayList<Integer>();
		Calendar c = Calendar.getInstance();
		Integer y = c.get(Calendar.YEAR);		
		for(int i = y-5; i > y-100; i--) {
			years.add(i);
		}
		
		days = new ArrayList<Integer>();
		for(int i = 1; i <= 31; i++) {
			days.add(i);
		}
		
		months = new HashMap<Integer,String>();
		months.put(1, "Jan");
		months.put(2, "Feb");
		months.put(3, "Mar");
		months.put(4, "Apr");
		months.put(5, "May");
		months.put(6, "Jun");
		months.put(7, "Jul");
		months.put(8, "Aug");
		months.put(9, "Sep");
		months.put(10, "Oct");
		months.put(11, "Nov");
		months.put(12, "Dec");		
	}
	
	public List<Integer> getYears() {
		return years;
	}

	public Map<Integer,String> getMonths() {
		return months;
	}

	public List<Integer> getDays() {
		return days;
	}

	public Integer getYear() {
		return year;
	}

	public Integer getMonth() {
		return month;
	}

	public Integer getDay() {
		return day;
	}

	public String getEmail() {
		return email;
	}

	public String getPassword() {
		return password;
	}

	public String getFirstName() {
		return firstName;
	}

	public String getLastName() {
		return lastName;
	}

	public String getGender() {
		return gender;
	}

	@RequiredStringValidator(key = "error.required", shortCircuit = true)
	@EmailValidator(key = "error.invalid")
	public void setEmail(String email) {
		this.email = email;
	}

	@RequiredStringValidator(key = "error.required", shortCircuit = true)
	@StringLengthFieldValidator(key = "error.length", trim = true, minLength = "6", maxLength = "20")
	public void setPassword(String password) {
		this.password = password;
	}
	
	@RequiredStringValidator(key = "error.required", shortCircuit = true)
	@StringLengthFieldValidator(key = "error.length", trim = true, minLength = "2", maxLength = "20")
	public void setFirstName(String firstName) {
		this.firstName = firstName;
	}

	@RequiredStringValidator(key = "error.required", shortCircuit = true)
	@StringLengthFieldValidator(key = "error.length", trim = true, minLength = "2", maxLength = "20")
	public void setLastName(String lastName) {
		this.lastName = lastName;
	}

	@RequiredStringValidator(key = "error.required")
	public void setGender(String gender) {
		this.gender = gender;
	}
	
	@FieldExpressionValidator(key = "error.required", expression = "year != -1")
	public void setYear(Integer year) {
		this.year = year;
	}

	@FieldExpressionValidator(key = "error.required", expression = "month != -1")
	public void setMonth(Integer month) {
		this.month = month;
	}
	
	@FieldExpressionValidator(key = "error.required", expression = "day != -1")
	public void setDay(Integer day) {
		this.day = day;
	}
	
	public void setYears(List<Integer> years) {
		this.years = years;
	}

	public void setMonths(Map<Integer,String> months) {
		this.months = months;
	}

	public void setDays(List<Integer> days) {
		this.days = days;
	}
	
	@SkipValidation
	public String execute() {
		return SUCCESS;
	}

	@Action(value = "/sign-up-add", results = { 
			@Result(name = "input", location="ajax-error.jsp"), 
			@Result(name = "success", location="ajax-msg.jsp") })
	public String add() throws Exception {
		String result = SUCCESS;
		HibernateSession hs = new HibernateSession();
		try {
			MemberDao memberDao = new MemberDao(hs);
			Member member = (Member)memberDao.find("email", email);
			if(member == null) {
				hs.beginTransaction();
				
				memberDao.insertOrUpdate(getMember());
				MailService ms = MailService.getInstance();
				member = (Member)memberDao.find("email", email);
				ms.sendActivationMail(member);
				
				hs.commitTransaction();
				addActionMessage(getText("success"));
			} else {
				addFieldError("email", getText("error.duplicate"));
				result = INPUT;
			}
		} catch (Exception e) {
			hs.rollbackTransaction(e);
			addActionError(getText("error.general"));
			result = INPUT;
		} finally {
			hs.closeSession();
		}

		return result;
	}

	private Member getMember() {
		Member member = new Member();
		member.setEmail(email);
		member.setPassword(password);
		member.setFirstName(firstName);
		member.setLastName(lastName);
		member.setGender(gender);
		Calendar c = Calendar.getInstance();
		c.set(Calendar.YEAR, year);
		c.set(Calendar.MONTH, month-1);
		c.set(Calendar.DATE, day);
		member.setBirthday(c.getTime());
		member.setActivationKey(Encoder.getRandomCode(7));
		member.setStatus(Constant.ACCOUNT_PENDING);
		return member;
	}
}